/*
 * Copyright 2025 arisgo@163.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.arisgo.cloud.flux.configurer;

import com.arisgo.cloud.flux.configurer.converter.HttpMessageConverterEncoder;
import com.arisgo.cloud.flux.configurer.resolve.ArisgoWebFluxErrorAttributes;
import com.arisgo.cloud.flux.configurer.resolve.ArisgoWebFluxExceptionHandler;
import com.arisgo.cloud.flux.mybatis.config.MybatisFlexProperties;
import com.arisgo.cloud.flux.mybatis.interceptor.MybatisInterceptor;
import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.spring.FlexSqlSessionFactoryBean;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.WebProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.config.WebFluxConfigurer;

import javax.sql.DataSource;

/**
 * @author Arisgo
 * @since 2024/6/9
 */
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties({ServerProperties.class, WebProperties.class, MybatisFlexProperties.class})
public class ArisgoWebFluxConfigurer implements WebFluxConfigurer {

    /**
     * Swagger3 配置
     */
    @Bean
    public OpenAPI openApi() {
        return new OpenAPI().info(new Info()
                .version("1.0")
                .title("Arisgo Cloud Web Mvc Api Manage")
                .description("Web Mvc Api Doc")
                .contact(new Contact().name("Arisgo").email("arisgo@163.com"))
                .license(new License().name("Apache 2.0")));
    }

    @Override
    public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
        configurer.customCodecs().register(new HttpMessageConverterEncoder());
    }

    /**
     * 配置 mybatis-flex
     */
    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource, MybatisFlexProperties mybatisFlexProperties, MybatisInterceptor mybatisInterceptor) throws Exception {
        // 关闭 banner
        FlexGlobalConfig.getDefaultConfig().setPrintBanner(mybatisFlexProperties.isPrintBanner());
        // 配置flex
        SqlSessionFactoryBean factoryBean = new FlexSqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        factoryBean.setPlugins(mybatisInterceptor);
        factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mybatisFlexProperties.getMapperLocations()));
        return factoryBean.getObject();
    }

    @Bean
    public ErrorAttributes getErrorAttributes() {
        return new ArisgoWebFluxErrorAttributes();
    }

    @Bean
    public ErrorWebExceptionHandler getErrorWebExceptionHandler(ErrorAttributes errorAttributes, WebProperties webProperties,
                                                                ServerProperties serverProperties, ApplicationContext applicationContext,
                                                                ServerCodecConfigurer serverCodecConfigurer) {
        return new ArisgoWebFluxExceptionHandler(errorAttributes, webProperties, serverProperties, applicationContext, serverCodecConfigurer);
    }

}
